package org.guegan.util.dircompare.main;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.guegan.util.dircompare.exception.DirCompareException;
import org.guegan.util.dircompare.exception.StopProcessException;
import org.guegan.util.dircompare.util.SessionUtil;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

public abstract class MainModule {
	private static Log log = LogFactory.getLog(MainModule.class);
	
	private SessionFactory sessionFactory;
	private Session session;
	private SessionUtil sessionUtil;
	private ProgressionCallbackListener listener;
	protected StringBuilder textOutput;
	protected Object result;

	public Object getResult() {
		return result;
	}

	public void setResult(Object result) {
		this.result = result;
	}

	public ProgressionCallbackListener getListener() {
		return listener;
	}

	public void setListener(ProgressionCallbackListener listener) {
		this.listener = listener;
	}

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
	
	protected Session getSession() {
		if (session == null || !session.isConnected()) {
			session = sessionFactory.openSession();
		}
		return session;
	}
	
	protected void closeSession() {
		if (session != null) {
			session.flush();
			session.close();
			session = null;
		}
	}
	
	protected SessionUtil getSessionUtil() {
		if (sessionUtil == null) {
			sessionUtil = new SessionUtil();
			sessionUtil.setSession(getSession());
		}
		return sessionUtil;
	}
	
	public void execute() {
		org.hibernate.Transaction trans = getSession().beginTransaction();
		try {
			result = textOutput = null;
			doExecute();
		}
		catch (Exception ex) {
			trans.rollback();
			trans = null;
			log.error("", ex);
			throw new DirCompareException("", ex);
		}
		finally {
			if (session.isConnected()) {
				if (trans != null) {
					trans.commit();
				}
				if (session != null) {
					session.close();
					session = null;
				}
			}
		}
	}

	protected abstract void doExecute() throws Exception;
	
	protected void callCallback(boolean isScanned) {
		if (listener != null) {
			if (listener.progressionCallback(isScanned)) {
				throw new StopProcessException();
			}
		}
	}

	public String getTextOutput() {
		return textOutput != null ? textOutput.toString() : null;
	}
	
	protected void report(String log, Log logger) {
		if (textOutput == null) {
			textOutput = new StringBuilder();
		}
		textOutput.append(log).append('\n');
		logger.info(log);
	}
	
}
